#include "Date.h"
#include <ctime>
#include "DateSerializer.h"

namespace etu {
namespace common {

Date Date::unkown() {
    Date ret;

    ret.day = 0;
    ret.month = 0;
    ret.year = 0;

    return ret;
}

bool Date::isUnkown(const Date& date) {
    return (date.day == 0) && (date.month == 0) && (date.year == 0);
}

Date Date::now() {
    return Date();
}

Date::Date() {
    time_t currentTime;
    time(&currentTime);
    struct tm currentDate = (* localtime(&currentTime));

    this->day = currentDate.tm_mday;
    this->month = currentDate.tm_mon + 1;
    this->year = currentDate.tm_year + 1900;
}

Date::Date(int _year, int _month, int _day) throw (IllegalArgumentException) {
    if(_year == 0 && _month == 0 && _day == 0) {
        // for a deserialization of a unknown date
        this->day = 0;
        this->month = 0;
        this->year = 0;
    } else {
        /*time_t rawTime;
        time(&rawTime);
        struct tm dateInfo = (* localtime(&rawTime));

        dateInfo.tm_year = _year - 1900;
        dateInfo.tm_mon = _month - 1;
        dateInfo.tm_mday = _day;
        time_t result = mktime(&dateInfo);

        if (result == -1) {
            throw IllegalArgumentException("Даты с заданымми параметрами не существует");
        }*/

        this->day = _day;
        this->month = _month;
        this->year = _year;
    }
}

Date::Date(const Date& orig) {
    this->year = orig.year;
    this->month = orig.month;
    this->day = orig.day;
}

Date::~Date() {
    //
}

int Date::getYear() const {
    return this->year;
}

int Date::getMonth() const {
    return this->month;
}

int Date::getDay() const {
    return this->day;
}

bool Date::operator==(const Date &date) const {
    return (this->day == date.day)
            && (this->month == date.month)
            && (this->year == date.year);
}

bool Date::operator!=(const Date &date) const {
    return (this->day != date.day)
            && (this->month != date.month)
            && (this->year != date.year);
}

bool Date::operator<(const Date &date) const {
    return (this->day < date.day)
            && (this->month < date.month)
            && (this->year < date.year);
}

bool Date::operator>(const Date &date) const {
    return (this->day > date.day)
            && (this->month > date.month)
            && (this->year > date.year);
}

bool Date::operator<=(const Date &date) const {
    return (this->day <= date.day)
            && (this->month <= date.month)
            && (this->year <= date.year);
}

bool Date::operator>=(const Date &date) const {
    return (this->day >= date.day)
            && (this->month >= date.month)
            && (this->year >= date.year);
}

std::ostream& operator<<(std::ostream& os, const Date& date) {
    Date* _date = (Date *) &date;
    DateSerializer serializer;
    os << serializer.serialize(_date);
    return os;
}

std::istream& operator>>(std::istream& is, Date& date) {
    DateSerializer serializer;
    std::string src;

    std::getline(is, src); // TODO

    Date* _date = serializer.deserialize(src);
    date.day = _date->day;
    date.month = _date->month;
    date.year = _date->year;
    delete _date;

    return is;
}

QDate Date::toQDate() const {
    return QDate(year,month,day);
}

Date Date::fromQDate(QDate date) {
	if (!date.isValid())
		return unkown();

    return Date(date.year(),date.month(),date.day());
}

}
}
